﻿using System;
using System.Data;
using System.Configuration;

using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Text;

public enum InclusionMode
{
	OnlyIncluded = 0, AllExceptExcluded = 1
}

public abstract class BaseMultiPartValue<T>
{
	#region PUBLIC
	#region INIT
	public BaseMultiPartValue()
	{
		Separators = new[] { ",", ";", "|", " " };
	}
	#endregion
	#region PROPS
	public string[] Separators { get; set; }
	/// <summary>
	/// Checks if any collection has been in use and if so, re-builds the string value from that collection.
	/// </summary>
	public virtual string Value
	{
		get
		{
			if (_valueList != null)
			{
				_value = GetValue(_valueList);
				NullifyLists();
			}
			return _value;
		}
		set
		{
			_value = value;
			NullifyLists();
		}
	}
	/// <summary>
	/// If this collection's last use was before the string value's last use, build the collection.
	/// </summary>
	public virtual List<T> ValueList
	{
		get
		{
			if (_valueList == null)
			{
				_valueList = new List<T>(GetValueList(Value)); // use the property here to ensure all other collections are nullifed.
			}
			return _valueList;
		}
	}
	#endregion
	#endregion
	#region INTERNAL
	#region VARS
	protected string _value;
	protected List<T> _valueList;
	#endregion
	#region METHODS
	protected virtual void NullifyLists()
	{
		_valueList = null;
	}
	protected abstract T[] GetValueList(string value);
	protected abstract string GetValue(List<T> valueList);
	#endregion
	#endregion
}
/// <summary>
/// Summary description for MultiPartValue
/// </summary>
public class MultiPartValue : BaseMultiPartValue<string>
{
	public MultiPartValue()
	{
	}
	public static void AddValue<T>(InclusionMode mode, List<T> list, T value)
	{
		if (mode == InclusionMode.OnlyIncluded)
		{
			foreach (T t in list)
			{
				if (object.Equals(t, value)) return;
			}
			list.Add(value);
		}
		else
		{
			foreach (T t in list)
			{
				if (object.Equals(t, value))
				{
					list.Remove(t);
					return;
				}
			}
		}
	}
	public static void RemoveValue<T>(InclusionMode mode, List<T> list, T value)
	{
		if (mode == InclusionMode.OnlyIncluded)
		{
			foreach (T t in list)
			{
				if (object.Equals(t, value))
				{
					list.Remove(t);
					return;
				}

			}
		}
		else
		{
			foreach (T t in list)
			{
				if (object.Equals(t, value))
					return;
			}
			list.Add(value);
		}
	}
	public static bool IsIncluded<T>(InclusionMode mode, IEnumerable<T> list, T value)
	{
		foreach (T t in list)
			if (object.Equals(t, value))
				return mode == InclusionMode.OnlyIncluded;
		return mode == InclusionMode.AllExceptExcluded;
	}
	public static IEnumerable<T> GetActiveList<T>(InclusionMode mode, IEnumerable<T> list, IEnumerable<T> completeList)
	{
		List<T> res = new List<T>();
		if (mode == InclusionMode.OnlyIncluded)
			res.AddRange(list);
		else
		{
			foreach (T t1 in completeList)
			{
				bool good = true;
				foreach (T t2 in list)
				{
					if (object.Equals(t1, t2))
					{
						good = false;
						break;
					}
				}
				if (good)
					res.Add(t1);
			}
		}
		return res;
	}

	protected override string[] GetValueList(string value)
	{
		return (value ?? "").Split(Separators, StringSplitOptions.RemoveEmptyEntries);
	}
	protected override string GetValue(List<string> valueList)
	{
		return string.Join(",", valueList.ToArray());
	}
}
public class MultiControlValue : BaseMultiPartValue<Control>
{
	public MultiControlValue(Control owner)
	{
		_owner = owner;
	}


	Control _owner;

	protected override Control[] GetValueList(string value)
	{
		List<Control> res = new List<Control>();
		foreach (string id in (value ?? "").Split(Separators, StringSplitOptions.RemoveEmptyEntries))
		{
			Control c = this._owner.FindControlGlobal(id);
			if (c == null)
				throw new InvalidOperationException("Control with ID '" + id + "' not found.");
			res.Add(c);
		}
		return res.ToArray();
	}

	protected override string GetValue(List<Control> valueList)
	{
		StringBuilder sbRes = new StringBuilder();
		foreach (Control c in valueList)
		{
			if (sbRes.Length > 0) sbRes.Append(Separators[0]);
			sbRes.Append(c.ID);
		}
		return sbRes.ToString();
	}
}

public delegate void SetValueDelegate(string value);